/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package jald

/*
 * Data
 */
//def n=' ВАСИЛЬЕВ НИКОЛАЙ НИКОЛАЕВИЧ'
//def n=' ВИКТОРОВ ЮРИЙ ОЛЕГОВИЧ'
n=Constants.name
if (n[0]!=' '){
    n =' '+n
}
c = Constants.coderTable
d = [:]
c.each{ key, value -> d[key]="x"+value }
c = d
def rules = [
    ["s",
        [
            [c[n[1]], c[n[2]], c[n[3]], "a"],
            [c[n[1]], c[n[4]], c[n[5]], "b"],
            [c[n[6]], "c"],
            [c[n[7]], "f"]
        ]
    ],
    ["a", 
        [
            [c[n[8]], "d"],
            [c[n[9]]]
        ]
    ],
    ["b",
        [
            [c[n[8]], "e"],
            [c[n[9]]]
        ]
    ],
    ["c",
        [
            [c[n[8]], "e"],
            [c[n[9]]]
        ]
    ],
    ["d",
        [
            [c[n[10]], "s"],
            [c[n[11]]]
        ]
    ],
    ["e", 
        [
            [c[n[10]], "s"],
            [c[n[11]]]
        ]
    ],
    ["f",
        [
            [c[n[12]],c[n[13]],c[n[14]],c[n[15]]],
            [c[n[16]],c[n[13]],c[n[14]],c[n[15]]],
            [c[n[17]],c[n[18]],c[n[15]]]
        ]        
    ]
]

/*
 * Data processing
 */

def linear_rules = []
def lineariser = {
    rule, output_rules
    ->
    def name = rule[0]
    def iteration = 0
    rule[1].each{
        r ->
        def local_rule_size = r.size() -1
        //println "${r} size ${local_rule_size}"
        if (local_rule_size > 0){
            for ( i in 0..local_rule_size ){
                def added_name = i==0? name : name + iteration
                if (i==local_rule_size-1 && r[i+1][0]!="x"){
                    output_rules.add(
                        [
                            added_name,
                            [r[i],r[i+1]]
                        ]
                    )
                    i++;
                    break;
                }
                def added_rule = [
                ]
                output_rules.add(
                    [
                        added_name,
                        i==local_rule_size ?
                        [r[i]] :
                        [
                            r[i],
                            i == local_rule_size && r[i][0]!="x" ?
                            r[i] : name+(++iteration)
                        ]
                    ]
                )
            }
        } else {
            output_rules.add( [name, r])
        }
    }
}
rules.each {
    rule -> lineariser(rule, linear_rules )
}

def unique_states = []
linear_rules.each{ if (!unique_states.contains(it[0])) {unique_states.add(it[0])} }

def unique_xses = []
c.each{if (!unique_xses.contains(it.value)) {unique_xses.add(it.value)} }
unique_xses.sort()

q_counter = 0
def q_table = [:]
unique_states.each{ q_table.put(it, "q${q_counter++}") }

/*
 * Text processing
 */
def code_table_text = {
    code_table ->
    def str = ""
    code_table.each{ str += "|${it.key==" "?"пробел":it.key}|${it.value}|\n"}
    return str
}
def rules_text = {
    def str = ""
    it.each{
        rule ->
        rule[1].each{
            str += "${rule[0]} -> "+it.join(" ")+"; "
        }
    }
    return str
}
def linear_rules_text = {
    def str=""
    it.each{ str += "${it[0]} -> ${it[1][0]}${it[1][1]==null?"":it[1][1]}; " }
    return str
}
def q_table_text = {
    def str = ""
    it.each{ str+= "${it.value} -> ${it.key}; " }
    return str
}
def undeterm_table_text = {
    xses, linears, states
    ->
    def str = ""
    states.each{
        q ->
        def move_to = [:]
        xses.each{move_to.put(it, [])}
        linears.each{
            r ->
            if( r[0].equals(q)){
                move_to[r[1][0]].add(r[1][1]!=null ? q_table[r[1][1]] : "exit")
            }
        }
        str += "| ${q_table[q]} |"
        //move_to.each{ str += it.value.size()==0?"<hr/>":it.value}
        def list = []
        move_to.each{ it.value.size()==0?list.add("<hr/>"):list.add(it.value) }
        str += list.join("|")+"|\n"
    }
    return str
}

def text = """

Задание для $n

h3. Таблица кодирования

${code_table_text(c)}

h3. Правила:

p. ${rules_text(rules)}


h3. Правила автоматной грамматики:

p. ${linear_rules_text(linear_rules)}

p. Всего ${linear_rules.size()} правил.


h3. Именование состояний:

p. ${q_table_text(q_table)}


h3. Таблица переходов недетерминированного автомата:

|_. state|_. ${unique_xses.join("|_. ")}|
${undeterm_table_text(unique_xses, linear_rules, unique_states)}

h3. Граф переходов недетерминированного автомата:

!undeterm.png!

"""
//println text
//println linear_rules

def graph_dot_text = {
    linears ->
    def str = "digraph undeterm {\n"
    linears.each{
        r ->
        str += "\t${q_table[r[0]]} -> "
        str += r[1][1]==null?"exit":q_table[r[1][1]]
        str += " [label=\"${r[1][0]}\"]"
        str += ";\n"
    } 
    str+="}\n"
    return str
}

def write_string = {
    out_file_name, string ->
    outFile = new File(out_file_name)
    appendFlag = false
    outStream = new FileOutputStream(outFile, appendFlag)
    writer = new FileWriter(outFile, appendFlag)
    outChannel = outStream.channel
    outFile << string
}
//outFile = new File("undeterm.dot")
//appendFlag = false
//outStream = new FileOutputStream(outFile, appendFlag)
//writer = new FileWriter(outFile, appendFlag)
//outChannel = outStream.channel
//
//outFile << graph_dot_text(linear_rules)

write_string(Constants.undetermDotFile, graph_dot_text(linear_rules))
write_string(Constants.textileOutFile, text)
write_string(Constants.pyTextileScript, Constants.pyTextileScriptCode)
Runtime.getRuntime().exec("dot -Tpng -o ${Constants.undetermGraphFile} ${Constants.undetermDotFile}")
Runtime.getRuntime().exec("python ${Constants.pyTextileScript} ${Constants.textileOutFile} ${Constants.htmlOutFile}")
